;/*
;++
;
; Copyright (c) 1992  Intel Corporation
; All rights reserved
;
; INTEL CORPORATION PROPRIETARY INFORMATION
;
; This software is supplied to Microsoft under the terms
; of a license agreement with Intel Corporation and may not be
; copied nor disclosed except in accordance with the terms
; of that agreement.
;
;
;   Module Name:
;
;       pcmp_nt.inc
;
;   Abstract:
;
;       include file for PC+MP system.
;
;       WARNING: This file is included by both ASM and C files.
;
;   Author:
;
;       Ron Mosgrove (Intel) 30-July-1993
;
;--
;

if 0        ; Begin C only code         */

#include "pcmp.inc"

//#define DEBUGGING       1

#ifdef DEBUGGING
extern CHAR Cbuf[];
#endif

//
//  To allow the user to specify command line options to the HAL.
//
#define USER_SETABLE_OPTIONS
// #define BUILD_FOR_OLD_IDW

//
//  Default BusType
//

#ifndef MCA
#define DEFAULT_PC_BUS      Eisa
#else
#define DEFAULT_PC_BUS      MicroChannel
#endif


//
//  Well known virtual address of local processor apic
//

#define LOCALAPIC   0xfffe0000
#define pLocalApic  ((volatile PULONG) LOCALAPIC)

//
//  Additional CpuFlags Bits used by NT in PC+MP Table
//
#define CPU_NT_STARTED      0x40    // CPU Has Been Started
#define CPU_NT_RUNNING      0x80    // CPU is Runing NT
#define MAX_PROCESSORS      8
#define MAX_IOAPICS         8

//
//  This OS specific structure holds useful MP information. This information
//  is obtained from the PC+MP table and stored here for convenience.
//
typedef struct HalpMpInfo {
    ULONG ApicVersion;      // 82489Dx or Not
    ULONG ProcessorCount;   // Number of Enabled Processors
    ULONG NtProcessors;     // Number of Running Processors
    ULONG BusCount;         // Number of buses in system
    ULONG IOApicCount;      // Number of Io Apics in system
    ULONG IntiCount;        // Number of Io Apic interrupt input entries
    ULONG LintiCount;       // Number of Local Apic interrupt input entries
    ULONG IMCRPresent;      // Indicates if the IMCR is present
    ULONG LocalApicBase;    // Base of local APIC
    PULONG IoApicBase[MAX_IOAPICS];     // The virtual addresses of the IoApics
    ULONG  IoApicPhys[MAX_IOAPICS];     // The physical addresses of the IoApics

// only good during initialization...
    PPCMPPROCESSOR ProcessorEntryPtr;       // Ptr to 1st PC+MP processor entry
    PPCMPBUS       BusEntryPtr;             // Ptr to 1st PC+MP bus  entry
    PPCMPIOAPIC    IoApicEntryPtr;          // Ptr to 1st PC+MP IoApic entry
    PPCMPINTI      IntiEntryPtr;            // Ptr to 1st PC+MP Inti entry
    PPCMPLINTI     LintiEntryPtr;           // Ptr to 1st PC+MP Linti entry
    PMPS_EXTENTRY  ExtensionTable;          // Ptr to 1st extension table entry
    PMPS_EXTENTRY  EndOfExtensionTable;
} ;

typedef struct {
    PUCHAR                  PcMpType;
    BOOLEAN                 PhysicalInstance;
    UCHAR                   Level;
    INTERFACE_TYPE          NtType;
    PINSTALL_BUS_HANDLER    NewInstance;
    BUS_DATA_TYPE           NtConfig;
    ULONG                   BusExtensionSize;
} PCMPBUSTRANS, *PPCMPBUSTRANS;

#define CFG_MUST_BE         0x02
#define CFG_ERROR           0x80

#define CFG_HIGH            0x01
#define CFG_LOW             0x00

#define CFG_EDGE            0x00
#define CFG_LEVEL           0x01
#define CFG_MB_EDGE         (CFG_MUST_BE | CFG_EDGE)
#define CFG_MB_LEVEL        (CFG_MUST_BE | CFG_LEVEL)
#define CFG_ERR_EDGE        (CFG_ERROR | CFG_EDGE)
#define CFG_ERR_LEVEL       (CFG_ERROR | CFG_LEVEL)
#define CFG_ERR_MB_EDGE     (CFG_ERROR | CFG_MUST_BE | CFG_EDGE)
#define CFG_ERR_MB_LEVEL    (CFG_ERROR | CFG_MUST_BE | CFG_LEVEL)

#define CFG_TYPE(a)     (a & 1)


//
// The kernel leaves some space (64 byte) of the PCR for the HAL to use
// as it needs.  Currently this space is used for some efficiency in
// some of the MP specific code and is highly implementation-dependent.
//

typedef struct {
    UCHAR           PCMPApicID;
    UCHAR           na[3];
} HALPRCB, *PHALPRCB;


//
// interrupt vector definitions for C
//

#define ZERO_VECTOR             0x00    // IRQL 00 placeholder
#define APIC_SPURIOUS_VECTOR    0x1f    // IRQL    Spurious handler
#define APC_VECTOR              0x3D    // IRQL 01 APC
#define DPC_VECTOR              0x41    // IRQL 02 DPC
#define APIC_REBOOT_VECTOR      0x50    // IRQL    Vector used to reboot
#define APIC_GENERIC_VECTOR     0xC1    // IRQL 27 broadcast function call
#define APIC_CLOCK_VECTOR       0xD1    // IRQL 28 APIC INTI0 - CLOCK2_LEVEL
#define APIC_SYNCH_VECTOR       0xD1    // IRQL 28 IPI_LEVEL-1
#define APIC_IPI_VECTOR         0xE1    // IRQL 29 APIC IPI

#define APIC_FAULT_VECTOR       0xE3    //
#define POWERFAIL_VECTOR        0xEF    // IRQL 30 reserved. not used

#define APIC_PROFILE_VECTOR     0xFD    // IRQL 31
#define APIC_PERF_VECTOR        0xFE    // IRQL 31
#define NMI_VECTOR              0xFF    // IRQL 31

//
//  8259/ISP interrupt controller register addresses
//

#define PIC1_PORT0              0x20
#define PIC1_PORT1              0x21
#ifndef PIC2_PORT0
#define PIC2_PORT0              0xA0
#define PIC2_PORT1              0xA1
#endif
#define PIC_SLAVE_IRQ           2


#define PIC1_ELCR_PORT          0x04D0  // ISP edge/level control registers
#define PIC2_ELCR_PORT          0x04D1

#define PIC1_SPURIOUS_VECTOR    0x37

//
// Defines for HalpFeatureBits
//

extern ULONG HalpFeatureBits;

//
//
//

ULONG FASTCALL HalpAcquireHighLevelLock(PKSPIN_LOCK);
VOID  FASTCALL HalpReleaseHighLevelLock(PKSPIN_LOCK, ULONG);
extern KSPIN_LOCK   HalpAccountingLock;
extern KAFFINITY    HalpActiveProcessors;

//
// Prototypes
//

BOOLEAN
HalpGetPcMpInterruptDesc (
    IN INTERFACE_TYPE BusType,
    IN ULONG BusNumber,
    IN ULONG BusInterruptLevel,
    OUT PULONG PcMpInti
    );

VOID
HalpCheckELCR (
    VOID
    );

VOID
HalpSetInternalVector (
    IN ULONG    InternalVector,
    IN VOID   (*HalInterruptSerivceRoutine)(VOID)
    );

VOID
HalpGenericCall (
    VOID        (*Fnc)(ULONG),
    ULONG       Context,
    KAFFINITY   Processors
    );

VOID
HalpPollForBroadcast (
    VOID
    );

ULONG
FASTCALL
HalpWaitForPending (
    IN ULONG    Count,
    IN volatile ULONG *LuICR
    );

VOID
HalpPerfInterrupt(
    VOID
    );

VOID
HalpEnablePerfInterupt (
    ULONG Context
    );

VOID
HalpEnableNMI (
    VOID
    );

NTSTATUS
HalpSetSystemInformation (
    IN HAL_SET_INFORMATION_CLASS    InformationClass,
    IN ULONG     BufferSize,
    IN PVOID     Buffer
    );

/*
endif
;
;  Begin assembly part of the definitions
;

include x86\pcmp.inc

;
;  Well known virtual address of local processor apic
;

LOCALAPIC   equ     0fffe0000h
APIC        equ     ds:[LOCALAPIC]

DEBUGGING       equ 0


if DEBUGGING
IRQL_METRICS        equ     0
endif
;
;  To allow the user to specify command line options to the HAL.
;
USER_SETABLE_OPTIONS    equ 1

;
;  This OS specific structure holds useful MP information. This information
;  is obtained from the PC+MP table and stored here for convenience.
;

HalpMpInfo struc
    ApicVersion     dd  0   ; 82489Dx or Not
    ProcessorCount  dd  0   ; Number of Enabled Processors
    NtProcessors    dd  0   ; Number of Running Processors
    BusCount        dd  0   ; Number of buses in system
    IOApicCount     dd  0   ; Number of Io Apics in system
    IntiCount       dd  0   ; Num of Io Apic interrupt inputs
    LintiCount      dd  0   ; Num of Local Apic interrupt inputs
    IMCRPresent     dd  0   ; Indicates if the IMCR is present
    LocalApicBase   dd  0   ; Base of local apic
    IoApicBase      dd  8  dup (0) ; The virtual addresses of the IoApics
    IoApicPhys      dd  8  dup (0) ; The physical addresses of the IoApics
    ProcessorEntryPtr   dd  0   ; Ptr to 1st PC+MP processor entry
    BusEntryPtr     dd  0   ; Ptr to 1st PC+MP bus  entry
    IoApicEntryPtr  dd  0   ; Ptr to 1st PC+MP IoApic entry
    IntiEntryPtr    dd  0   ; Ptr to 1st PC+MP Inti entry
    LintiEntryPtr   dd  0   ; Ptr to 1st PC+MP Linti entry
    ExtensionTable  dd  0   ; Ptr to 1st extension table entry
    EndExtensionTable dd  0 ; Ptr to 1st extension table entry
HalpMpInfo ends


;
;  interrupt vector definitions for assembler
;

ZERO_VECTOR             equ     000h    ;  IRQL 00 placeholder
APIC_SPURIOUS_VECTOR    equ     01fh    ;  Vector used for spurious handler
APC_VECTOR              equ     03Dh    ;  IRQL 01 APC
DPC_VECTOR              equ     041h    ;  IRQL 02 DPC
APIC_REBOOT_VECTOR      equ     050h    ;  Vector used to reboot
DEVICE_LEVEL1           equ     051h
DEVICE_LEVEL2           equ     061h
DEVICE_LEVEL3           equ     071h
DEVICE_LEVEL4           equ     081h
DEVICE_LEVEL5           equ     091h
DEVICE_LEVEL6           equ     0A1h
DEVICE_LEVEL7           equ     0B1h
APIC_GENERIC_VECTOR     equ     0C1h    ;  IRQL 27 broadcast function call
APIC_CLOCK_VECTOR       equ     0D1h    ;  IRQL 28 APIC INTI0 - CLOCK2_LEVEL
APIC_SYNCH_VECTOR       equ     0D1h    ;  IRQL 28 IPI_LEVEL-1
APIC_IPI_VECTOR         equ     0E1h    ;  IRQL 29 APIC IPI

APIC_FAULT_VECTOR       equ     0E3h    ;
POWERFAIL_VECTOR        equ     0EFh    ;  IRQL 30 reserved

APIC_PROFILE_VECTOR     equ     0FDh    ;  IRQL 27
APIC_PERF_VECTOR        equ     0FEh    ;  IRQL 27
NMI_VECTOR              equ     0FFh    ;  IRQL 31

HAL_PROFILE_LEVEL       equ     HIGH_LEVEL

;
;  8259/ISP interrupt controller register addresses
;

PIC1_PORT0          equ     020H
PIC1_PORT1          equ     021H
PIC2_PORT0          equ     0A0H
PIC2_PORT1          equ     0A1H

PIC1_ELCR_PORT      equ     04D0H   ; ISP edge/level control registers
PIC2_ELCR_PORT      equ     04D1H

;
; Initialization control words for the PICs
;

ICW1_ICW4_NEEDED                equ     01H
ICW1_CASCADE                    equ     00H
ICW1_INTERVAL8                  equ     00H
ICW1_LEVEL_TRIG                 equ     08H
ICW1_EDGE_TRIG                  equ     00H
ICW1_ICW                        equ     10H

ICW4_8086_MODE                  equ     001H
ICW4_AUTO_EOI                   equ     002H
ICW4_NORM_EOI                   equ     000H
ICW4_NON_BUF_MODE               equ     000H
ICW4_SPEC_FULLY_NESTED          equ     010H
ICW4_NOT_SPEC_FULLY_NESTED      equ     000H

PIC_SLAVE_IRQ                   equ     2
PIC1_BASE                       equ     30H
PIC2_BASE                       equ     38H
PIC_CLOCK_VECTOR                equ     30H
PIC_DMA_VECTOR                  equ     3DH
PIC1_SPURIOUS_VECTOR            equ     37H
PIC2_SPURIOUS_VECTOR            equ     3FH

;
;  Operation control words for the PICs
;

OCW2_NON_SPECIFIC_EOI   equ     020H
OCW2_SPECIFIC_EOI       equ     060H
OCW3_READ_ISR           equ     0BH
OCW3_READ_IRR           equ     0AH
OCW3_READ_POLLED        equ     0CH

;
; A couple of definitions that shouldn't change on a Compatible
;

TimerPicInti        equ     0
DmaPic2Inti         equ     5
SlavePicInti        equ     2
DmaPicInti          equ     13  ; DMA input relative to 0

cr                  equ 0ah
lf                  equ 0dh

;
; The kernel leaves some space (64 byte) of the PCR for the HAL to use
; as it needs.  Currently this space is used for some efficiency in
; some of the MP specific code and is highly implementation-dependent.
;


PcrE struc
    PcrNumber           db      0           ; Processor's number
    ShortDpc            db      0           ; Short circut dpc interrupt
    DpcPending          db      0           ; Dpc interrupt pending

                        db      0               ; force dword alignment
    ;
    ;   The next three dwords are used to manipulate the APIC counter
    ;

    ApicClockFreqHz     dd      0           ; Counter Freq in Hertz
    ApicClockFreqKhz    dd      0           ; Counter Freq in Khertz (rounded)
    ProfileCountDown    dd      0           ; Current Countdown Interval

    TSCHz               dd      0           ; Time stamp counter hertz low


    ; PerfCounterLow      dd      0           ; PerProcessor Counter
    ; PerfCounterHigh     dd      0           ;
    ; ProfileCountLast    dd      0

PcrE ends

PrcbE struc
    PrcbPCMPApicID      db      0           ; Processor's PCMP ApicID
                        db      3 dup (0)       ; force dword alignment
PrcbE ends


MsrTSC  equ     10h

;++
;
;   STALL_WHILE_APIC_BUSY
;
;   Wait for the APIC DELIVERY_PENDING bit to be clear
;
;--

STALL_WHILE_APIC_BUSY macro
    local   a, b
if 0

        push    eax
        mov     eax, 5000h

a:      test    dword ptr APIC[LU_INT_CMD_LOW],DELIVERY_PENDING
        jz      short b

        dec     eax
        jnz     short a

        int 3
        jmp     short a

b:      pop     eax

else

a:      test    dword ptr APIC[LU_INT_CMD_LOW],DELIVERY_PENDING
        jnz     short a

endif
endm

;++
;
;   APICFIX
;
;   Macro Description:
;
;       For internal testing use
;
;   Arguments:
;
;       None
;
;--

APICFIX macro reg1
    ;    inc     dword ptr PCR[PcKernel]           ; Count # of times patched
endm

;++
;
;   CHECKTPR
;
;   Macro Description:
;
;       For internal testing use
;
;   Arguments:
;
;       None
;
;--

CHECKTPR macro reg1, reg2
if DBG
        cmp     reg1, reg2
        je      short @f
        int 3
@@:
endif
endm

;++
;
;   IODELAY
;
;   Macro Description:
;
;       This macro delays the CPU just a little so the PIC has time to settle
;       between IO port accesses.  Current mechanism is to read an APIC local
;       unit register (eax is saved).  Note that PUSHF/POPF is worth 10 clocks.
;
;   Arguments:
;
;       None
;
;--

IODELAY macro
        pushf
        popf
        jmp     $+2
endm

;++
;
;   SET_8259_MASK
;
;   Macro Description:
;
;       This macro sets the 8259 PIC interrupt mask register with the mask
;       passed from eax register.  Bits 7:0 are the mask for the master PIC
;       and bits 15:8 are the mask for the slave PIC.
;
;   Arguments:
;
;       (eax) = mask for setting 8259 PIC interrupt mask register
;
;--

SET_8259_MASK   macro

        out     PIC1_PORT1, al          ; set master 8259 mask
        shr     eax, 8                  ; shift slave 8259 mask to al
        out     PIC2_PORT1, al          ; set slave 8259 mask
endm

;*/
